import Vue from "vue";
import {
    debounce
} from "@u/lodash/throttle";
import jude from "../Tools/Jude";
import {
    qs,
    getNumber
} from "../util";
import {
    Storage
} from "../Storage";
//#ifdef H5
//#endif

Promise.prototype.finally = function (callback) {
    let P = this.constructor;
    return this.then(
        (value) => P.resolve(callback(value)).then(() => value),
        (reason) =>
            P.resolve(callback(reason)).then(() => {
                throw reason;
            })
    );
};

//#ifndef MP-WEIXIN
var Fly = require("flyio/dist/npm/fly");
//#endif
//#ifdef MP-WEIXIN
var Fly = require("flyio/dist/npm/wx");
//#endif
let timer = null;

const showModal = debounce(function (obj = {}) {
    uni.showModal(obj);
}, 300);

let REQUEST_QUEUE = [];

export default class Basic {
    static BasicUrl = "";
    static isPopup = false;
    static Prefix = "";
    /**
     * 刷新用户基本信息
     *
     */
    static refreshUserInfo = debounce(function () {
        Vue.getBasicUserInfoSync()
    }, 500)

    constructor(opts = {}, basicUrl) {
        if (jude.isString(basicUrl) && basicUrl.trim() !== "")
            this.basicUrl = basicUrl;
        else this.basicUrl = jude.isString(opts.basicUrl) ? opts.basicUrl : "";
        if (jude.isString(opts.prefix) && opts.prefix.trim() !== "")
            this.prefix = opts.prefix.replace(/^\/+|\/+$/, "");
    }

    /**
     * 登录获取sessionKey (微信)
     * @returns {Promise<unknown>}
     */
    getSessionKey() {
        const vm = this;
        const session_key = Storage.getStorageSync("session_key");
        if (typeof session_key !== "string" || jude.isEmpty(session_key)) {
            return vm.getLogin();
        } else {
            return new Promise(async (resolve) => {
                uni.checkSession({
                    success() {
                        resolve({
                            session_key
                        });
                    },
                    async fail() {
                        const result = await vm.getLogin();
                        resolve(result);
                    },
                });
            });
        }
    }

    getLogin() {
        return new Promise((resolve, reject) => {
            uni.login({
                complete(data) {
                    resolve(data);
                },
            });
        });
    }

    static toLogin(code) {
        console.log(
            Vue.NEED_AFRESH_LOGIN.indexOf(code) > -1,
            code,
            "是否前往登录页面"
        );
        Vue.NEED_AFRESH_LOGIN.indexOf(code) > -1 &&
        Vue.$global_util.Login.toLogin();
    }

    /**
     * 显示弹窗
     * @param message 提示文案
     * @param code 状态
     * @param type 0 默认 1 不弹窗 2 不重定向
     * @returns {Promise<never>}
     */
    static async showLoginModal(message, code, type = 0) {
        const {
            Login,
            getCurrentPageSync
        } = Vue.$global_util;
        if (Basic.isPopup) return Promise.reject();
        const page = await getCurrentPageSync();
        if (page.$$$isPathRedirect === false) {
            setTimeout(() => (page.$$$isPathRedirect = true), 500);
            return Promise.resolve();
        }
        const home_active_path = Storage.getStorageSync('home_active_path') || 0;
        const fIndex = Vue.VERIFY_LINK.findIndex(value => {
            const paths = value.split(',');
            if (paths.length === 1 && page.route === value) return true;
            else if (page.route === paths[0] && typeof home_active_path === "number") {
                return Number(paths[1]) === home_active_path;
            }
        })
        if (fIndex === -1) {
            if (type === 0 || code === 4600) {
                const token = Storage.getStorageSync('token');
                console.log(Login.isFirstLogin, "是首次进入用户");
                Login.isFirstLogin = !token;
                if (!Login.isFirstLogin) {
                    Basic.isPopup = true;
                    const isLogin = Vue.NEED_AFRESH_LOGIN.indexOf(code) > -1
                    showModal({
                        content: Vue.ERROR_STATUS[code] || message,
                        showCancel: isLogin,
                        confirmText: isLogin ? "立即前往" : "我知道了",
                        success({
                                    confirm,
                                    cancel
                                }) {
                            if (isLogin && confirm === true) {
                                Basic.redirectFun(code);
                            } else if (isLogin && cancel === true) {
                                Vue.signOut()
                                Vue.$$router.replaceAll("/pages/home/index")
                            }
                        },
                        complete() {
                            Basic.isPopup = false;
                        },
                    });
                } else Basic.redirectFun(code);
            }
            return Promise.reject();
        } else {
            return Promise.resolve({
                code: -1
            });
        }
    }

    static redirectFun(code) {
        Basic.toLogin(code);
    }

    static token;

    static async request() {
        const options = jude.isObject(arguments[0]) ? arguments[0] : {};
        const {
            fly,
            url,
            data,
            refreshTokenApi
        } = Basic.getFly(...arguments);
        const isRefreshToken = Vue.$global_util.Login.isRefreshToken,
            refreshTokenUrl = Vue.$global_util.Login.refreshTokenUrl,
            isRefreshUserInfo = Vue.$global_util.Login.isRefreshUserInfo;
        // console.log(options.refreshTokenApi, url, 'obj.isRefreshToken', refreshTokenUrl, isRefreshToken, isRefreshUserInfo);
        // 判断是否需要刷新token
        if (refreshTokenUrl && options.url.indexOf(refreshTokenUrl) > -1 || options.refreshTokenApi === true) {
            return fly.request(url, data);
        } else if (REQUEST_QUEUE.length > 0) {
            return new Promise(resolve => {
                uni.$once("refreshTokenSuccess", async function () {
                    Vue.$global_util.Login.refreshTokenUrl = null;
                    let result = await fly.request(url, data);
                    resolve(result)
                })
            })
        } else if (isRefreshToken === true || isRefreshUserInfo === true) {
            REQUEST_QUEUE.push({
                url,
                data
            });
            let result;
            if (isRefreshToken) {
                result = await Vue.$ajax.Temp.refreshToken();
                Vue.$global_util.Login.isRefreshToken = false;
            } else {
                result = await Vue.$ajax.Temp.getBasicUserInfo();
                Vue.$global_util.Login.isRefreshUserInfo = false;
            }
            uni.$emit('refreshTokenSuccess', result);
            REQUEST_QUEUE = [];
            if (result && result.code === 0) Basic.token = result.data && result.data.token;
            const {
                fly,
                url,
                data
            } = Basic.getFly(...arguments);
            Basic.token = null;
            return fly.request(url, data);
        }
        return fly.request(url, data);
    }

    static getFly() {
        const options = jude.isObject(arguments[0]) ? arguments[0] : {};
        let {
            url,
            data,
            baseURL,
            timeout,
            headers,
            responseType,
            dataType,
            method,
            contentType,
            isRedirect
        } = options;
        if (method && 'post get put POST GET PUT'.indexOf(method) > -1) {
            method = method.toUpperCase()
        } else {
            method = 'GET'
        }
        const fly = new Fly();
        //#ifdef H5
        fly.engine = XMLHttpRequest;
        //#endif

        // 配置请求参数
        const config = {};

        config.timeout = timeout || 15000;
        config.headers = {
            'Content-Type': contentType || 'application/json', // 默认值
            'X-Requested-With': 'XMLHttpRequest', // 默认值
            // 'admin': Vue.$config.admin,// 版本
            ...headers
        };

        if (Vue.$config.source_name) config.headers['source_name'] = Vue.$config.source_name;
        if (baseURL) config.baseURL = baseURL;

        config.responseType = 'text';
        config.dataType = dataType || 'json';
        config.parseJson = !dataType || dataType.toUpperCase() === 'JSON';
        config.method = method || 'GET';
        config.withCredentials = true;

        try {
            // console.log(Basic.token, '是否刷新token', url);
            const LoginData = jude.isEmpty(Basic.token) ? Vue.$global_util.Login.getLogin() : {
                token: Basic.token
            };
            if (LoginData.token) config.headers['token'] = `${LoginData.token}`;
        } catch (e) {

        }

        Object.assign(fly.config, config);
        // 添加请求拦截器
        fly.interceptors.request.use((config, promise) => {
            //给所有请求添加自定义header
            process.env.NODE_ENV === 'development' && console.warn(config, '请求配置');
            return config;
        });

        // 添加响应拦截器，响应拦截器会在then/catch处理之前执行
        fly.interceptors.response.use(
            async result => {
                //只将请求结果的data字段返回
                if (result.status === 500) {
                    throw 'systemError:Unknown error occurred in the system'
                }
                let url, str = '';
                console.log(`__请求成功__${str}__`, result.data);
                try {
                    url = result.request.url;
                    if (url) {
                        const a = url.split('/');
                        str = a[a.length - 1];
                        if (str) str = str.split('?')[0];
                    }

                    if (typeof result.data !== 'object') {
                        // 兼容JSON字符串类型返回数据
                        try {
                            result.data = JSON.parse(result.data)
                        } catch (e) {

                        }
                    }
                    if (typeof result.data !== 'object') {
                        // 返回数据体非对象时为系统错误
                        throw 'systemError:Unknown error occurred in the system'
                    }
                    // 将返回数据体中状态强制转化Number类型
                    // result.data.code = getNumber(result.data.code, 0);
                    const code = result.data.code;
                    // 将返回数据体中数据info 兼容&统一 data
                    // let resultData = null;
                    // if (!jude.isEmpty(result.data.data)) resultData = result.data.data;

                    const message = !jude.isEmpty(result.data.message) ? result.data.message : null;

                    // 判断info&data是否为字符串类型  是：就是提示信息 （兼容）
                    // if (resultData && typeof resultData === 'string' && !message) {
                    //     result.data.message = resultData;
                    //     result.data.data = null;
                    // } else if (!jude.isEmpty(resultData)) {
                    //     result.data.info = resultData;
                    //     result.data.data = resultData;
                    // } else {
                    //     result.data.data = null;
                    //     result.data.info = null;
                    // }
                    console.log(`__请求成功2__${str}__`, result.data, !!Vue.ERROR_STATUS[code], isRedirect);
                    if (Vue.NEED_AFRESH_LOGIN.indexOf(code) > -1) {
                        if (isRedirect === false) return Promise.resolve(result.data);
                        await Basic.showLoginModal(message, code);
                    } else if (Vue.NEED_AFRESH_REFRESH.indexOf(code) > -1) {
                        Vue.$toast.text(Vue.ERROR_STATUS[code]);
                        result.data.code = 0;
                        Vue.$global_util.Login.isRefreshUserInfo = true;
                    }
                    return result.data;
                } catch (err) {
                    console.log(`__________请求失败{${str}:false,msg:${err}____________`);
                    throw `请求失败{${str}:false,msg:${err}}`;
                }
            },
            errMsg => {
                console.log("+++++++++++连接失败+++++++++++", errMsg);
                //发生网络错误后会走到这里
                let flag = typeof errMsg === "string" && errMsg.indexOf('请求失败') > -1;
                const message = flag ? errMsg : `网络连接失败，请检查网络是否连接正常`;
                showModal({
                    title: '温馨提示',
                    content: message,
                    showCancel: false,
                    success: function (res) {
                        if (res.confirm) {
                            console.log('用户点击确定')
                        } else if (res.cancel) {
                            console.log('用户点击取消')
                        }
                    }
                });
                uni.hideLoading()
                return Promise.reject();
            }
        );

        // const share_id = Vue.$Storage.getStorageSync('share_id');
        // // const get_info = qs.stringify({_f: Vue.$config._f, share_id: share_id});
        // switch (true) {
        //     case /\?|\&/ig.test(url):
        //         url = url.replace(/\?/ig, `?${get_info}&`);
        //         break;
        //     case /\?/ig.test(url):
        //         url = url.replace(/\?/ig, `?${get_info}`);
        //         break;
        //     case /\#/ig.test(url):
        //         url = url.replace(/\#/ig, `?${get_info}#`);
        //         break;
        //     default:
        //         url += `?${get_info}`;
        // }

        return {
            url,
            data,
            fly
        }
    }

    /**
     * 过滤对象数据（不传无用数据）
     * @param obj
     * @returns {*[]}
     */
    filterObj(obj) {
        for (let key in obj)
            if (jude.isEmpty(obj[key])) delete obj[key];
        return {
            ...obj
        };
    }

    /**
     * 过滤数组（不传无用数据）
     * @param list
     * @returns {*[]}
     */
    filterArr(list) {
        for (let i = 1; list.length - 1; i++) {
            if (jude.isEmpty(list[i])) list[i] = null;
            else if (jude.isObject(list[i])) this.filterObj(list[i]);
            else if (jude.isArray(list[i]) && list[i].length > 0)
                this.filterArr(list[i]);
        }
        return [...list];
    }

    /**
     * 去除重复 /
     * @param str
     * @returns {string}
     */
    slashTrim(str) {
        return typeof str === "string" ? str.replace(/^\/+|\/+$/, "") : "";
    }

    /**
     * 请求事件封装
     *
     * @param obj 请求参数与配置信息
     * @param method 请求方法
     * @param sendType POST 请求类型（JSON & 表单）json：JSON类型；string：表单类型
     * @returns {Promise<never>|Promise<unknown>|Promise<void>}
     */
    request(obj, method = 'GET', sendType = 'string') {
        const {
            Login
        } = Vue.$global_util;
        if (!jude.isObject(obj) || jude.isEmptyObject(obj) || !obj.url) return Promise.reject();
        let contentType = '';
        const headers = {};
        let data = {};
        const basicUrl = this.basicUrl || Basic.BasicUrl;
        let url = basicUrl.replace(/\/+$/, '');
        if (/^https?:\/\//.test(obj.url)) {
            url = obj.url
        } else if (/^\/+(service|api)/ig.test(obj.url)) {
            url += `/${this.slashTrim(obj.url)}`
        } else {
            let prefix = this.prefix || Basic.Prefix || '';
            if (!jude.isEmpty(prefix)) prefix = `/${this.slashTrim(prefix)}`;
            url += `${prefix}/${this.slashTrim(obj.url)}`;
        }

        // 移除 空字符串 空数组 空对象 null undefined
        switch (!!obj.data) {
            case jude.isObject(obj.data):
                data = this.filterObj(obj.data);
                break;
            case jude.isArray(obj.data):
                data = this.filterArr(obj.data);
                break;
        }
        console.log(`url: ${obj.url}`);
        console.log(`method: ${method}`);
        console.log(`query: --------start--------`);
        for (let k in data) console.log(`----------${k}：${JSON.stringify(data[k])}`);
        console.log(`query: --------end--------`);


        method = method && 'post get put POST GET PUT'.indexOf(method) > -1 ? method.toUpperCase() : 'GET';
        if ((method === 'POST' || method === "PUT") && sendType === 'string') {
            data = qs.stringify(data);
            contentType = 'application/x-www-form-urlencoded'
        }
        if (obj.isAuth === true && !Login.token) {
            if (obj.isRedirect === false) return Promise.resolve();
            return Basic.showLoginModal(null, 4002);
        }
        return Basic.request({
            url,
            data,
            method,
            headers,
            contentType,
            isRedirect: obj.isRedirect,
            refreshTokenApi: obj.isRefreshToken
        })
    }

    /**
     * GET请求
     * @param opts
     * @returns {Promise<never>|Promise<unknown>|Promise<void>}
     */
    get(opts) {
        return this.request(opts, "get");
    }

    /**
     * POST请求（json数据结构）（一般后台在body取）
     * @param opts
     * @returns {Promise<never>|Promise<unknown>|Promise<void>}
     */
    post_json(opts) {
        return this.request(opts, "post", "json");
    }

    post_put(opts) {
        return this.request(opts, "put");
    }

    /**
     * POST请求（表单数据结构）（key1=123&key2=122212）
     * @param opts
     * @returns {Promise<never>|Promise<unknown>|Promise<void>}
     */
    post(opts) {
        return this.request(opts, "post");
    }

}
